HAL FMC NOR initialization and configuration functions migration

The goal of this page is to show how to migrate the initialization sequence using STM32CubeMX2:

  • Open STM32CubeMX2 FMC NOR configuration panel.

  • Configure the SW layer HAL.

  • Configure the FMC NOR main features.

  • Configure the FMC NOR advanced features.

  • Configure the FMC NOR security and privilege features if needed.

  • Configure the FMC NOR GPIO pins.

  • Generate the code.

Note

The FMC NOR peripheral supports the following read and write access modes:

  • Asynchronous memory HAL_NOR_SetConfigRdWrAsyncMemory(), with an optional configuration to set different timings for write operations when needed using HAL_NOR_SetWrAsyncTimings().

  • Synchronous/Asynchronous memory HAL_NOR_SetConfigRdSyncWrAsyncMemory().

HAL FMC NOR configuration panel

Create a new project with STM32CubeMX2, start by enabling the FMC instance as NOR, as shown in this example with the selected FMC-NOR_PSRAM1, then start the initialization and the main configuration.

Project configuration panel

HAL FMC NOR main features configuration

Configure the FMC NOR main features.

FMC NOR main feature configuration

HAL FMC NOR advanced features configuration

Configure the advanced FMC NOR features.

FMC NOR advanced feature configuration

HAL FMC NOR security and privilege features configuration

Configure the FMC NOR security and privilege features if needed.

FMC NOR security and privilege feature configuration

GPIO configuration

Configure GPIO pins.

FMC NOR GPIO configuration

Generated FMC NOR initialization and de-initialization sequences

The FMC NOR initialization sequence is generated in the mx_fmc_nor_psram1_nor_init function in mx_fmc.c file under $YOUR_PROJECT_NAME$/$YOUR_PROJECT_NAME$_SW/generated/STM32Cube_CodeGen.

Related concepts:

STM32CubeMX2 Generated : FMC NOR initialization and de-initialization sequences

Topic

Code Snippet HAL1

Code Snippet HAL2

Handle declaration

NOR_HandleTypeDef hnor1;


GPIO_InitTypeDef GPIO_InitStruct ={0};
hal_nor_handle_t hNOR_PSRAM1;
hal_nor_config_t nor_config;
hal_nor_rd_wr_async_memory_config_t p_config;
hal_gpio_config_t  gpio_config;

Initialization and configuration sequence

static void MX_FMC_Init(void)
{

  FMC_NORSRAM_TimingTypeDef Timing = {0};

  /** Perform the NOR1 memory initialization sequence
  */
  hnor1.Instance = FMC_NORSRAM_DEVICE;
  hnor1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
  /* hnor1.Init */
  hnor1.Init.NSBank = FMC_NORSRAM_BANK1;
  hnor1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
  hnor1.Init.MemoryType = FMC_MEMORY_TYPE_NOR;
  hnor1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
  hnor1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
  hnor1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
  hnor1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
  hnor1.Init.WriteOperation = FMC_WRITE_OPERATION_DISABLE;
  hnor1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
  hnor1.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
  hnor1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
  hnor1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
  hnor1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
  hnor1.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE;
  hnor1.Init.NBLSetupTime = 0;
  hnor1.Init.PageSize = FMC_PAGE_SIZE_NONE;
  hnor1.Init.MaxChipSelectPulse = DISABLE;
  /* Timing */
  Timing.AddressSetupTime = 3;
  Timing.AddressHoldTime = 1;
  Timing.DataSetupTime = 3;
  Timing.DataHoldTime = 1;
  Timing.BusTurnAroundDuration = 1;
  Timing.CLKDivision = 2;
  Timing.DataLatency = 2;
  Timing.AccessMode = FMC_ACCESS_MODE_A;
  /* ExtTiming */

  if (HAL_NOR_Init(&hnor1, &Timing, NULL) != HAL_OK)
  {
    Error_Handler( );
  }

}

static void HAL_FMC_MspInit(void){

  if (FMC_Initialized) {
    return;
  }
  FMC_Initialized = 1;

  __HAL_RCC_FMC_CLK_ENABLE();

  GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_7 | GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_5 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_12 | GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

}

void HAL_NOR_MspInit(NOR_HandleTypeDef* hnor)
{
  HAL_FMC_MspInit();
}


static void MX_GPIO_Init(void)
{

  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOF_CLK_ENABLE();

}
hal_nor_handle_t *mx_fmc_nor_psram1_nor_init(void)
{

  if (HAL_NOR_Init(&hNOR_PSRAM1, HAL_NOR1) != HAL_OK)
  {
    return NULL;
  }

  HAL_RCC_FMC_EnableClock();

  nor_config.wait_signal_polarity = HAL_NOR_WAIT_SIGNAL_POLARITY_LOW;

  if (HAL_NOR_SetConfig(&hNOR_PSRAM1, &nor_config) != HAL_OK)
  {
    return NULL;
  }

 /* Asynchronous read and write with identical timing for both operation */

 p_config.memory.mux_data_addr                   = HAL_NOR_MUX_DATA_ADDR_DISABLE;
 p_config.timings.access_timings.addr_setup_nsec = 20;
 p_config.timings.access_timings.addr_hold_nsec  = 10;
 p_config.timings.access_timings.data_setup_nsec = 30;
 p_config.timings.access_timings.data_hold_nsec  = 10;
 p_config.timings.async_wait                     = HAL_NOR_ASYNC_WAIT_SIGNAL_DISABLE;
 p_config.timings.bus_turnaround_nsec            = 10;
 if (HAL_NOR_SetConfigRdWrAsyncMemory(&hNOR_PSRAM1, &p_config) != HAL_OK)
  {
    return NULL;
  }

  HAL_NOR_EnableMemory(&hNOR_PSRAM1);

  HAL_RCC_GPIOC_EnableClock();

  HAL_RCC_GPIOD_EnableClock();

  HAL_RCC_GPIOA_EnableClock();

  HAL_RCC_GPIOB_EnableClock();


  gpio_config.mode        = HAL_GPIO_MODE_ALTERNATE;
  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
  gpio_config.pull        = HAL_GPIO_PULL_NO;
  gpio_config.speed       = HAL_GPIO_SPEED_FREQ_LOW;
  gpio_config.alternate   = HAL_GPIO_AF_12;
  HAL_GPIO_Init(HAL_GPIOC, HAL_GPIO_PIN_1 | HAL_GPIO_PIN_2 | HAL_GPIO_PIN_3 | HAL_GPIO_PIN_4 | HAL_GPIO_PIN_5, &gpio_config);

  gpio_config.mode        = HAL_GPIO_MODE_ALTERNATE;
  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
  gpio_config.pull        = HAL_GPIO_PULL_NO;
  gpio_config.speed       = HAL_GPIO_SPEED_FREQ_LOW;
  gpio_config.alternate   = HAL_GPIO_AF_12;
  HAL_GPIO_Init(HAL_GPIOD, HAL_GPIO_PIN_12, &gpio_config);

  gpio_config.mode        = HAL_GPIO_MODE_ALTERNATE;
  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
  gpio_config.pull        = HAL_GPIO_PULL_NO;
  gpio_config.speed       = HAL_GPIO_SPEED_FREQ_LOW;
  gpio_config.alternate   = HAL_GPIO_AF_10;
  HAL_GPIO_Init(HAL_GPIOD, HAL_GPIO_PIN_8 | HAL_GPIO_PIN_9, &gpio_config);


  gpio_config.mode        = HAL_GPIO_MODE_ALTERNATE;
  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
  gpio_config.pull        = HAL_GPIO_PULL_NO;
  gpio_config.speed       = HAL_GPIO_SPEED_FREQ_LOW;
  gpio_config.alternate   = HAL_GPIO_AF_12;
  HAL_GPIO_Init(HAL_GPIOA, HAL_GPIO_PIN_12 | HAL_GPIO_PIN_11 | HAL_GPIO_PIN_10 | HAL_GPIO_PIN_9 | HAL_GPIO_PIN_2 | HAL_GPIO_PIN_1 | HAL_GPIO_PIN_0 | HAL_GPIO_PIN_5, &gpio_config);

  gpio_config.mode        = HAL_GPIO_MODE_ALTERNATE;
  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
  gpio_config.pull        = HAL_GPIO_PULL_NO;
  gpio_config.speed       = HAL_GPIO_SPEED_FREQ_LOW;
  gpio_config.alternate   = HAL_GPIO_AF_12;
  HAL_GPIO_Init(HAL_GPIOB, HAL_GPIO_PIN_11 | HAL_GPIO_PIN_15 | HAL_GPIO_PIN_5 | HAL_GPIO_PIN_13 | HAL_GPIO_PIN_12 | HAL_GPIO_PIN_2, &gpio_config);


  gpio_config.mode        = HAL_GPIO_MODE_ALTERNATE;
  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
  gpio_config.pull        = HAL_GPIO_PULL_UP;
  gpio_config.speed       = HAL_GPIO_SPEED_FREQ_LOW;
  gpio_config.alternate   = HAL_GPIO_AF_12;
  HAL_GPIO_Init(HAL_GPIOB, HAL_GPIO_PIN_4, &gpio_config);

  gpio_config.mode        = HAL_GPIO_MODE_ALTERNATE;
  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
  gpio_config.pull        = HAL_GPIO_PULL_NO;
  gpio_config.speed       = HAL_GPIO_SPEED_FREQ_VERY_HIGH;
  gpio_config.alternate   = HAL_GPIO_AF_12;
  HAL_GPIO_Init(HAL_GPIOB, HAL_GPIO_PIN_3, &gpio_config);

  gpio_config.mode        = HAL_GPIO_MODE_ALTERNATE;
  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
  gpio_config.pull        = HAL_GPIO_PULL_UP;
  gpio_config.speed       = HAL_GPIO_SPEED_FREQ_LOW;
  gpio_config.alternate   = HAL_GPIO_AF_12;
  HAL_GPIO_Init(HAL_GPIOA, HAL_GPIO_PIN_15, &gpio_config);

  gpio_config.mode        = HAL_GPIO_MODE_ALTERNATE;
  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
  gpio_config.pull        = HAL_GPIO_PULL_NO;
  gpio_config.speed       = HAL_GPIO_SPEED_FREQ_LOW;
  gpio_config.alternate   = HAL_GPIO_AF_10;
  HAL_GPIO_Init(HAL_GPIOB, HAL_GPIO_PIN_0, &gpio_config);

  gpio_config.mode        = HAL_GPIO_MODE_ALTERNATE;
  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
  gpio_config.pull        = HAL_GPIO_PULL_NO;
  gpio_config.speed       = HAL_GPIO_SPEED_FREQ_LOW;
  gpio_config.alternate   = HAL_GPIO_AF_7;
  HAL_GPIO_Init(HAL_GPIOB, HAL_GPIO_PIN_1, &gpio_config);

  return &hNOR_PSRAM1;
}

Deinitialization sequence

static void HAL_FMC_MspDeInit(void){

if (FMC_DeInitialized) {
    return;
  }
  FMC_DeInitialized = 1;
  /* Peripheral clock enable */
  __HAL_RCC_FMC_CLK_DISABLE();

  HAL_GPIO_DeInit(GPIOD, GPIO_PIN_4 | GPIO_PIN_7 | GPIO_PIN_5);

  HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_5 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_12 | GPIO_PIN_13);

}

void HAL_NOR_MspDeInit(NOR_HandleTypeDef* hnor){

  HAL_FMC_MspDeInit();
}
void mx_fmc_nor_psram1_nor_deinit(void)
{
  /* De-initialize all GPIO pins associated with FMC */
  HAL_GPIO_DeInit(HAL_GPIOC, HAL_GPIO_PIN_1 | HAL_GPIO_PIN_2 | HAL_GPIO_PIN_3 | HAL_GPIO_PIN_4 | HAL_GPIO_PIN_5);

  HAL_GPIO_DeInit(HAL_GPIOD, HAL_GPIO_PIN_8 | HAL_GPIO_PIN_9 | HAL_GPIO_PIN_12);

  HAL_GPIO_DeInit(HAL_GPIOA, HAL_GPIO_PIN_0 | HAL_GPIO_PIN_1 | HAL_GPIO_PIN_2 | HAL_GPIO_PIN_5 | HAL_GPIO_PIN_9 | \
                             HAL_GPIO_PIN_10 | HAL_GPIO_PIN_11 | HAL_GPIO_PIN_12 | HAL_GPIO_PIN_15);

  HAL_GPIO_DeInit(HAL_GPIOB, HAL_GPIO_PIN_0 | HAL_GPIO_PIN_1 | HAL_GPIO_PIN_2 | HAL_GPIO_PIN_3 | HAL_GPIO_PIN_4 | \
                             HAL_GPIO_PIN_5 | HAL_GPIO_PIN_11 | HAL_GPIO_PIN_12 | HAL_GPIO_PIN_13 | HAL_GPIO_PIN_15);

  HAL_NOR_DeInit(&hNOR_PSRAM1);
}

All subbanks configuration

HAL1 code snippet

HAL2 code snippet

HAL_Init();

// --- NOR bank (1) and sub-banks Initialization NORx (x = 1 to 4) ---
for (int i = 0; i < 4; i++)
{
   hnor[i].Instance = FMC_NORSRAM_DEVICE;
   hnor[i].Extended = FMC_NORSRAM_EXTENDED_DEVICE;
   hnor[i].Init.NSBank             = FMC_NORSRAM_BANK1 + i;
   hnor[i].Init.DataAddressMux     = FMC_DATA_ADDRESS_MUX_DISABLE;
   hnor[i].Init.WriteOperation     = FMC_WRITE_OPERATION_ENABLE;
   hnor[i].Init.BurstAccessMode    = FMC_BURST_ACCESS_MODE_DISABLE;
   hnor[i].Init.WrapMode           = FMC_WRAP_MODE_DISABLE;
   hnor[i].Init.WaitSignalActive   = FMC_WAIT_TIMING_BEFORE_WS;
   hnor[i].Init.WaitSignal         = FMC_WAIT_SIGNAL_DISABLE;
   hnor[i].Init.ExtendedMode       = FMC_EXTENDED_MODE_DISABLE;
   hnor[i].Init.WriteBurst         = FMC_WRITE_BURST_DISABLE;
   hnor[i].Init.ContinuousClock    = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;

   // Fill static configuration
   hnor[i].Init.MemoryType         = FMC_MEMORY_TYPE_NOR;
   /* ---------------------------------------------------------- */
   hnor[i].Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;

   // Fill memory configuration
   hnor[i].Init.MemoryDataWidth    = FMC_NORSRAM_MEM_BUS_WIDTH_16;

   hnor[i].Init.AsynchronousWait   = FMC_ASYNCHRONOUS_WAIT_DISABLE;
   Nor_Timing.AddressSetupTime      = 2;
   Nor_Timing.AddressHoldTime       = 1;
   Nor_Timing.DataSetupTime         = 2;
   Nor_Timing.DataHoldTime          = 1;
   Nor_Timing.BusTurnAroundDuration = 1;
   Nor_Timing.CLKDivision           = 2;
   Nor_Timing.DataLatency           = 2;

   /* Optional: Set different write timings if needed */
   Nor_Wr_Timing.AddressSetupTime      = 3;
   Nor_Wr_Timing.AddressHoldTime       = 1;
   Nor_Wr_Timing.DataSetupTime         = 3;
   Nor_Wr_Timing.DataHoldTime          = 1;
   Nor_Wr_Timing.BusTurnAroundDuration = 1;
   Nor_Wr_Timing.AccessMode            = FMC_ACCESS_MODE_A;

   HAL_NOR_Init(&hnor[i], &Nor_Timing, &Nor_Wr_Timing);
}
hal_nor_handle_t* hnor [4] ={hnor1, hnor2, hnor3, hnor4};

hal_nor_t nor_instance[4] = {HAL_NOR1, HAL_NOR2, HAL_NOR3, HAL_NOR4};

HAL_Init();

// Initialize the NOR handle and associate to the HAL NORx instance
for (int i = 0; i < 4; i++)
{
   HAL_NOR_Init(&hnor[i], nor_instance[i]);
}

// Fill static configuration of FMC peripheral
nor_config.wait_signal_polarity = HAL_NOR_WAIT_SIGNAL_POLARITY_LOW;

/* Fill memory configuration */
nor_mem_config.memory.mux_data_addr = HAL_NOR_MUX_DATA_ADDR_DISABLE;

nor_mem_config.timings.async_wait = HAL_NOR_ASYNC_WAIT_SIGNAL_DISABLE;
nor_mem_config.timings.access_timings.addr_setup_nsec = 20;
nor_mem_config.timings.access_timings.addr_hold_nsec = 10;
nor_mem_config.timings.access_timings.data_setup_nsec = 20;
nor_mem_config.timings.access_timings.data_hold_nsec = 10;
nor_mem_config.timings.bus_turnaround_nsec = 10;

/* Optional: Set different write timings if needed */
nor_wr_timings.async_access_timings.addr_setup_nsec = 30;
nor_wr_timings.async_access_timings.addr_hold_nsec = 10;
nor_wr_timings.async_access_timings.data_setup_nsec = 30;
nor_wr_timings.async_access_timings.data_hold_nsec = 10;
nor_wr_timings.bus_turnaround_nsec = 10;
nor_wr_timings.read_access_mode = HAL_NOR_ACCESS_MODE_B;
nor_wr_timings.write_access_mode = HAL_NOR_ACCESS_MODE_B;

for (int i = 0; i < 4; i++)
{
   HAL_NOR_SetConfig(&hnor[i], &nor_config); // FMC peripheral configuration
   HAL_NOR_SetConfigRdWrAsyncMemory(&hnor[i], &nor_mem_config); // FMC memory configuration
   HAL_NOR_SetWrAsyncTimings(&hnor[i], &nor_wr_timings); // Optional: FMC write timing configuration when different timing needed for write operation
   HAL_NOR_EnableMemory(&hnor[i]); // Enable the NOR sub-bank x
}